#include <QHBoxLayout>
#include <QEvent>
#include <QMouseEvent>
#include <QApplication>
#include <QFont>
#include <QPainter>
#include <QFile>
#include <QTextStream>
#include <QDebug>

#include "widgetpar.h"

TitleBar::TitleBar(QWidget *parent) :
    QWidget(parent)
{
    this->setObjectName("TitleBar");

    TiBar_pLeftSpacing  = new QLabel(this);
    TiBar_pIconLabel    = new QLabel(this);
    TiBar_pTitleLabel   = new QLabel(this);
    TiBar_pSkinBtn      = new QPushButton(this);
    TiBar_pSettingsBtn  = new QPushButton(this);
    TiBar_pUpgradeBtn   = new QPushButton(this);
    TiBar_pLockBtn      = new QPushButton(this);
    TiBar_pQuestionBtn  = new QPushButton(this);
    TiBar_pMinimizeBtn  = new QPushButton(this);
    TiBar_pMaximizeBtn  = new QPushButton(this);
    TiBar_pCloseBtn     = new QPushButton(this);
    TiBar_pSkinBtn->setFlat(true);
    TiBar_pSettingsBtn->setFlat(true);
    TiBar_pUpgradeBtn->setFlat(true);
    TiBar_pLockBtn->setFlat(true);
    TiBar_pQuestionBtn->setFlat(true);
    TiBar_pMinimizeBtn->setFlat(true);
    TiBar_pMaximizeBtn->setFlat(true);
    TiBar_pCloseBtn->setFlat(true);

//    QFont font = TiBar_pTitleLabel->font();
//    font.setFamily("Microsoft YaHei");
//    TiBar_pTitleLabel->setFont(font);

    TiBar_pLeftSpacing->setFixedSize(1, 4);
    TiBar_pLeftSpacing->setMinimumWidth(4);
    TiBar_pLeftSpacing->setText("");

    TiBar_pIconLabel->setFixedSize(20, 20); //设置图标固定大小
    TiBar_pIconLabel->setScaledContents(true);  //设置图片显示合适大小

    TiBar_pTitleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);//此属性保存窗口小部件的默认布局行为。

    TiBar_pSkinBtn->setFixedSize(45, 29);
    TiBar_pSettingsBtn->setFixedSize(45, 29);
    TiBar_pUpgradeBtn->setFixedSize(45, 29);
    TiBar_pLockBtn->setFixedSize(45, 29);
    TiBar_pQuestionBtn->setFixedSize(45, 29);
    TiBar_pMinimizeBtn->setFixedSize(45, 29);//设置三个按钮的固定大小
    TiBar_pMaximizeBtn->setFixedSize(45, 29);
    TiBar_pCloseBtn->setFixedSize(45, 29);
    TiBar_pTitleLabel->setFixedHeight(29);
    this->setMinimumHeight(29);

    TiBar_pLeftSpacing->setObjectName("TiBar_leftspacingLabel");
    TiBar_pTitleLabel->setObjectName("TiBar_titleLabel"); //此属性保存此对象的名称。
    TiBar_pSkinBtn->setObjectName("TiBar_skinButton");
    TiBar_pSettingsBtn->setObjectName("TiBar_settingsButton");
    TiBar_pUpgradeBtn->setObjectName("TiBar_UpgradeButton");
    TiBar_pLockBtn->setObjectName("TiBar_LockButton");
    TiBar_pQuestionBtn->setObjectName("TiBar_questionButton");
    TiBar_pMinimizeBtn->setObjectName("TiBar_minimizeButton");
    TiBar_pMaximizeBtn->setObjectName("TiBar_maximizeButton");
    TiBar_pCloseBtn->setObjectName("TiBar_closeButton");

    TiBar_pSkinBtn->setProperty("TiBar_maximizeProperty", "maximize");
    TiBar_pSettingsBtn->setProperty("TiBar_maximizeProperty", "maximize");
    TiBar_pUpgradeBtn->setProperty("TiBar_maximizeProperty", "maximize");
    TiBar_pLockBtn->setProperty("TiBar_maximizeProperty", "maximize");
    TiBar_pQuestionBtn->setProperty("TiBar_maximizeProperty", "maximize");
    TiBar_pMinimizeBtn->setProperty("TiBar_maximizeProperty", "maximize");
    TiBar_pMaximizeBtn->setProperty("TiBar_maximizeProperty", "maximize");
    TiBar_pCloseBtn->setProperty("TiBar_maximizeProperty", "maximize");

    TiBar_pSkinBtn->setToolTip("换装");
    TiBar_pSettingsBtn->setToolTip("设置");
    TiBar_pUpgradeBtn->setToolTip("有你没玩过的船新版本可升级");
    TiBar_pLockBtn->setToolTip("置顶");
    TiBar_pQuestionBtn->setToolTip("帮助");
    TiBar_pMinimizeBtn->setToolTip("最小化"); //鼠标停留在上面的提示
    TiBar_pMaximizeBtn->setToolTip("最大化");
    TiBar_pCloseBtn->setToolTip("关闭");

    QHBoxLayout *pLayout = new QHBoxLayout(this);
    pLayout->setObjectName("LayoutTitle");
    pLayout->addWidget(TiBar_pLeftSpacing);
    pLayout->addSpacing(1);
    pLayout->addWidget(TiBar_pIconLabel);
    pLayout->addSpacing(6);
    pLayout->addWidget(TiBar_pTitleLabel);
    pLayout->addSpacing(5);
    pLayout->addWidget(TiBar_pSkinBtn);
    pLayout->addWidget(TiBar_pSettingsBtn);
    pLayout->addWidget(TiBar_pUpgradeBtn);
    pLayout->addWidget(TiBar_pLockBtn);
    pLayout->addWidget(TiBar_pQuestionBtn);
    pLayout->addWidget(TiBar_pMinimizeBtn);
    pLayout->addWidget(TiBar_pMaximizeBtn);
    pLayout->addWidget(TiBar_pCloseBtn);
    pLayout->setSpacing(0);//设置控件之间的间距
    pLayout->setContentsMargins(0, 0, 0, 0);//设置左上右下的边距

    this->setLayout(pLayout);

    connect(TiBar_pSkinBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));
    connect(TiBar_pSettingsBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));
    connect(TiBar_pUpgradeBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));
    connect(TiBar_pLockBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));
    connect(TiBar_pQuestionBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));
    connect(TiBar_pMinimizeBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));
    connect(TiBar_pMaximizeBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));
    connect(TiBar_pCloseBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));

    TiBar_pSkinBtn->hide();
    TiBar_pSettingsBtn->hide();
    TiBar_pUpgradeBtn->hide();
    TiBar_pLockBtn->hide();
    TiBar_pQuestionBtn->hide();

    update();
}

void TitleBar::showSkinBtn(bool state)
{
    if (state)
    {
        TiBar_pSkinBtn->show();
    }
    else
    {
        TiBar_pSkinBtn->hide();
    }
}

void TitleBar::showSettingBtn(bool state)
{
    if (state) TiBar_pSettingsBtn->show();
    else TiBar_pSettingsBtn->hide();
}

void TitleBar::showUpgradeBtn(bool state)
{
    if (state) TiBar_pUpgradeBtn->show();
    else TiBar_pUpgradeBtn->hide();
}
void TitleBar::showLockBtn(bool state)
{
    if (state) TiBar_pLockBtn->show();
    else TiBar_pLockBtn->hide();
}
void TitleBar::showQuestionBtn(bool state)
{
    if (state) TiBar_pQuestionBtn->show();
    else TiBar_pQuestionBtn->hide();
}

void TitleBar::EnableSkinBtn(bool state)
{
    TiBar_pSkinBtn->setEnabled(state);
}

void TitleBar::EnableSettingBtn(bool state)
{
    TiBar_pSettingsBtn->setEnabled(state);
}

void TitleBar::EnableUpgradeBtn(bool state)
{
    TiBar_pUpgradeBtn->setEnabled(state);
}
void TitleBar::EnableLockBtn(bool state)
{
    TiBar_pLockBtn->setEnabled(state);
}
void TitleBar::EnableQuestioinBtn(bool state)
{
    TiBar_pQuestionBtn->setEnabled(state);
}

void TitleBar::showMinmizeBtn(bool state)
{
    if (state) TiBar_pMinimizeBtn->show();
    else TiBar_pMinimizeBtn->hide();
}
void TitleBar::showMaxmizeBtn(bool state)
{
    if (state) TiBar_pMaximizeBtn->show();
    else TiBar_pMaximizeBtn->hide();
}
void TitleBar::showCloseBtn(bool state)
{
    if (state) TiBar_pCloseBtn->show();
    else TiBar_pCloseBtn->hide();
}
void TitleBar::EnableMinmizeBtn(bool state)
{
    TiBar_pMinimizeBtn->setEnabled(state);
}
void TitleBar::EnableMaxmizeBtn(bool state)
{
    TiBar_pMaximizeBtn->setEnabled(state);
}
void TitleBar::EnableCloseBtn(bool state)
{
    TiBar_pCloseBtn->setEnabled(state);
}

void TitleBar::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)
    QStyleOption styleOpt;
    styleOpt.init(this);
    QPainter painter(this);
    style()->drawPrimitive(QStyle::PE_Widget, &styleOpt, &painter, this);
}

/*  标题栏右上角三个按钮的槽函数*/
void TitleBar::on_TiBar_Clicked()
{
    QPushButton *pBtn = qobject_cast<QPushButton *>(sender());//如果在由信号激活的槽中调用，则返回指向发送信号的对象的指针; 否则它返回0.
    /*  返回此窗口小部件的窗口，即具有（或可能具有）窗口系统框架的下一个祖先窗口小部件。 如果窗口小部件是窗口，则返回窗口小部件本身。*/
    QWidget *pWindow = this->window();
    if (pWindow->isWindow())//如果窗口小部件是独立窗口，则返回true，否则返回false。
    {
        if (pBtn == TiBar_pSkinBtn)
        {
            emit OpenClothesSignal();
        }
        else if (pBtn == TiBar_pSettingsBtn)
        {
            emit OpenSettingsSignal();
        }
        else if (pBtn == TiBar_pUpgradeBtn)
        {
            emit UpGradeSignal();
        }
        else if (pBtn == TiBar_pLockBtn)
        {
            if (TiBar_pLockBtn->objectName() == "TiBar_LockButton")
            {
                Qt::WindowFlags m_flags = pWindow->windowFlags();
                pWindow->setWindowFlags(m_flags | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
                pWindow->show();
                TiBar_pLockBtn->setToolTip("取消置顶");
                TiBar_pLockBtn->setObjectName("TiBar_UnlockButton");
            }
            else if (TiBar_pLockBtn->objectName() == "TiBar_UnlockButton")
            {
                Qt::WindowFlags m_flags = nullptr;
                pWindow->window()->setWindowFlags(m_flags | Qt::FramelessWindowHint);
                pWindow->show();
                TiBar_pLockBtn->setToolTip("置顶");
                TiBar_pLockBtn->setObjectName("TiBar_LockButton");
            }
            TiBar_pLockBtn->setStyle(QApplication::style());
        }
        else if (pBtn == TiBar_pQuestionBtn)
        {
            emit QuestionSignal();
        }
        else if (pBtn == TiBar_pMinimizeBtn)
        {
            pWindow->showMinimized();//最小化窗口小部件，作为图标。调用此函数仅影响窗口。
        }
        else if (pBtn == TiBar_pMaximizeBtn)
        {
            pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();//放大缩小
        }
        else if (pBtn == TiBar_pCloseBtn)
        {
            pWindow->close();//关闭窗口
        }
    }
}

bool TitleBar::getLockState()
{
    if (TiBar_pLockBtn->objectName() == "TiBar_LockButton")
    {
        return false;
    }
    else if (TiBar_pLockBtn->objectName() == "TiBar_UnlockButton")
    {
        return true;
    }
    return true;
}

void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event)
    if (TiBar_pMaximizeBtn->isVisible())
    {
        if (TiBar_pMaximizeBtn->isEnabled())
        {
            emit TiBar_pMaximizeBtn->clicked();
        }
    }
}

//void TitleBar::mousePressEvent(QMouseEvent *event)
//{
//    if (ReleaseCapture())
//    {
//        QWidget *pWindow = this->window();
//        if (pWindow->isWindow())
//        {
//           SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
//        }
//    }
//    event->ignore();
//}

bool TitleBar::eventFilter(QObject *obj, QEvent *event)
{
    switch (event->type())
    {
        case QEvent::WindowTitleChange:
        {
            QWidget *pWidget = qobject_cast<QWidget *>(obj);
            if (pWidget)
            {
                TiBar_pTitleLabel->setText(pWidget->windowTitle());
                return true;
            }
            break;
        }
        case QEvent::WindowIconChange:
        {
            QWidget *pWidget = qobject_cast<QWidget *>(obj);
            if (pWidget)
            {
                QIcon icon = pWidget->windowIcon();
                TiBar_pIconLabel->setPixmap(icon.pixmap(TiBar_pIconLabel->size()));
                return true;
            }
            break;
        }
        case QEvent::WindowStateChange:
        case QEvent::Resize:
            updateMaximize();
            break;
        default:
            break;
    }
    return QWidget::eventFilter(obj, event);
}
//窗口大小发生改变
void TitleBar::updateMaximize()
{
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        bool bMaximize = pWindow->isMaximized();
        if (bMaximize)
        {
            TiBar_pSkinBtn->setProperty("TiBar_maximizeProperty", "restore");
            TiBar_pSettingsBtn->setProperty("TiBar_maximizeProperty", "restore");
            TiBar_pUpgradeBtn->setProperty("TiBar_maximizeProperty", "restore");
            TiBar_pLockBtn->setProperty("TiBar_maximizeProperty", "restore");
            TiBar_pQuestionBtn->setProperty("TiBar_maximizeProperty", "restore");
            TiBar_pMinimizeBtn->setProperty("TiBar_maximizeProperty", "restore");
            TiBar_pMaximizeBtn->setProperty("TiBar_maximizeProperty", "restore");
            TiBar_pCloseBtn->setProperty("TiBar_maximizeProperty", "restore");
            TiBar_pMaximizeBtn->setToolTip("向下还原");
            TiBar_pSkinBtn->setFixedHeight(22);
            TiBar_pSettingsBtn->setFixedHeight(22);
            TiBar_pUpgradeBtn->setFixedHeight(22);
            TiBar_pLockBtn->setFixedHeight(22);
            TiBar_pQuestionBtn->setFixedHeight(22);
            TiBar_pMinimizeBtn->setFixedHeight(22);
            TiBar_pMaximizeBtn->setFixedHeight(22);
            TiBar_pCloseBtn->setFixedHeight(22);
            TiBar_pTitleLabel->setFixedHeight(22);
            this->setMinimumHeight(22);
            TiBar_pLeftSpacing->hide();
        }
        else
        {
            TiBar_pSkinBtn->setProperty("TiBar_maximizeProperty", "maximize");
            TiBar_pSettingsBtn->setProperty("TiBar_maximizeProperty", "maximize");
            TiBar_pUpgradeBtn->setProperty("TiBar_maximizeProperty", "maximize");
            TiBar_pLockBtn->setProperty("TiBar_maximizeProperty", "maximize");
            TiBar_pQuestionBtn->setProperty("TiBar_maximizeProperty", "maximize");
            TiBar_pMinimizeBtn->setProperty("TiBar_maximizeProperty", "maximize");
            TiBar_pMaximizeBtn->setProperty("TiBar_maximizeProperty", "maximize");
            TiBar_pCloseBtn->setProperty("TiBar_maximizeProperty", "maximize");
            TiBar_pMaximizeBtn->setToolTip("最大化");
            TiBar_pSkinBtn->setFixedHeight(29);
            TiBar_pSettingsBtn->setFixedHeight(29);
            TiBar_pUpgradeBtn->setFixedHeight(29);
            TiBar_pLockBtn->setFixedHeight(29);
            TiBar_pQuestionBtn->setFixedHeight(29);
            TiBar_pMinimizeBtn->setFixedHeight(29);
            TiBar_pMaximizeBtn->setFixedHeight(29);
            TiBar_pCloseBtn->setFixedHeight(29);
            TiBar_pTitleLabel->setFixedHeight(29);
            this->setMinimumHeight(29);
            TiBar_pLeftSpacing->show();
        }
        TiBar_pSkinBtn->setStyle(QApplication::style());
        TiBar_pSettingsBtn->setStyle(QApplication::style());
        TiBar_pUpgradeBtn->setStyle(QApplication::style());
        TiBar_pLockBtn->setStyle(QApplication::style());
        TiBar_pQuestionBtn->setStyle(QApplication::style());
        TiBar_pMinimizeBtn->setStyle(QApplication::style());
        TiBar_pMaximizeBtn->setStyle(QApplication::style());
        TiBar_pCloseBtn->setStyle(QApplication::style());
    }
}

/*****
 * CursorPosCalculator
 * 计算鼠标是否位于左、上、右、下、左上角、左下角、右上角、右下角
*****/
class CursorPosCalculator
{
public:
    explicit CursorPosCalculator();
    void reset();
    void recalculate(const QPoint &globalMousePos, const QRect &frameRect);

public:
    bool m_bOnEdges              : true;
    bool m_bOnLeftEdge           : true;
    bool m_bOnRightEdge          : true;
    bool m_bOnTopEdge            : true;
    bool m_bOnBottomEdge         : true;
    bool m_bOnTopLeftEdge        : true;
    bool m_bOnBottomLeftEdge     : true;
    bool m_bOnTopRightEdge       : true;
    bool m_bOnBottomRightEdge    : true;

    static int m_nBorderWidth;
    static int m_nTitleHeight;
};

///
/// \brief 更新鼠标样式、移动窗体、缩放窗体
///
class WidgetData
{
public:
    explicit WidgetData(FramelessHelperPrivate *d, QWidget *pTopLevelWidget);
    ~WidgetData();
    QWidget* widget();
    // 处理鼠标事件-划过、按下、释放、移动
    void handleWidgetEvent(QEvent *event);
    // 更新橡皮筋状态
    void updateRubberBandStatus();

private:
    // 更新鼠标样式
    void updateCursorShape(const QPoint &gMousePos);
    // 重置窗体大小
    void resizeWidget(const QPoint &gMousePos);
    // 移动窗体
    void moveWidget(const QPoint &gMousePos);
    // 处理鼠标按下
    void handleMousePressEvent(QMouseEvent *event);
    // 处理鼠标释放
    void handleMouseReleaseEvent(QMouseEvent *event);
    // 处理鼠标移动
    void handleMouseMoveEvent(QMouseEvent *event);
    // 处理鼠标离开
    void handleLeaveEvent(QEvent *event);
    // 处理鼠标进入
    void handleHoverMoveEvent(QHoverEvent *event);

private:
    FramelessHelperPrivate *d;
    QRubberBand *m_pRubberBand;
    QWidget *m_pWidget;
    QPoint m_ptDragPos;
    CursorPosCalculator m_pressedMousePos;
    CursorPosCalculator m_moveMousePos;
    bool m_bLeftButtonPressed;
    bool m_bCursorShapeChanged;
    bool m_bLeftButtonTitlePressed;
    Qt::WindowFlags m_windowFlags;
};

/*****
 * FramelessHelperPrivate
 * 存储界面对应的数据集合，以及是否可移动、可缩放属性
*****/
class FramelessHelperPrivate
{
public:
    QHash<QWidget*, WidgetData*> m_widgetDataHash;
    ///
    /// \brief 窗口是否可移动
    ///
    bool m_bWidgetMovable        : true;
    ///
    /// \brief 窗口是否可缩放
    ///
    bool m_bWidgetResizable      : true;
    ///
    /// \brief 橡皮筋是否可缩放
    ///
    bool m_bRubberBandOnResize   : true;
    ///
    /// \brief 橡皮筋是否可移动
    ///
    bool m_bRubberBandOnMove     : true;
};



int CursorPosCalculator::m_nBorderWidth = 5;
int CursorPosCalculator::m_nTitleHeight = 30;

/***** CursorPosCalculator *****/
CursorPosCalculator::CursorPosCalculator()
{
    reset();
}

void CursorPosCalculator::reset()
{
    m_bOnEdges = false;
    m_bOnLeftEdge = false;
    m_bOnRightEdge = false;
    m_bOnTopEdge = false;
    m_bOnBottomEdge = false;
    m_bOnTopLeftEdge = false;
    m_bOnBottomLeftEdge = false;
    m_bOnTopRightEdge  = false;
    m_bOnBottomRightEdge = false;
}

void CursorPosCalculator::recalculate(const QPoint &gMousePos, const QRect &frameRect)
{
    int globalMouseX = gMousePos.x();
    int globalMouseY = gMousePos.y();

    int frameX = frameRect.x();
    int frameY = frameRect.y();

    int frameWidth = frameRect.width();
    int frameHeight = frameRect.height();

    m_bOnLeftEdge = (globalMouseX >= frameX &&
                  globalMouseX <= frameX + m_nBorderWidth );


    m_bOnRightEdge = (globalMouseX >= frameX + frameWidth - m_nBorderWidth &&
                   globalMouseX <= frameX + frameWidth);

    m_bOnTopEdge = (globalMouseY >= frameY &&
                 globalMouseY <= frameY + m_nBorderWidth );

    m_bOnBottomEdge = (globalMouseY >= frameY + frameHeight - m_nBorderWidth &&
                    globalMouseY <= frameY + frameHeight);

    m_bOnTopLeftEdge = m_bOnTopEdge && m_bOnLeftEdge;
    m_bOnBottomLeftEdge = m_bOnBottomEdge && m_bOnLeftEdge;
    m_bOnTopRightEdge = m_bOnTopEdge && m_bOnRightEdge;
    m_bOnBottomRightEdge = m_bOnBottomEdge && m_bOnRightEdge;

    m_bOnEdges = m_bOnLeftEdge || m_bOnRightEdge || m_bOnTopEdge || m_bOnBottomEdge;
}



/***** WidgetData *****/
WidgetData::WidgetData(FramelessHelperPrivate *_d, QWidget *pTopLevelWidget)
{
    d = _d;
    m_pWidget = pTopLevelWidget;
    m_bLeftButtonPressed = false;
    m_bCursorShapeChanged = false;
    m_bLeftButtonTitlePressed = false;
    m_pRubberBand = nullptr;

    m_windowFlags = m_pWidget->windowFlags();
    m_pWidget->setMouseTracking(true);
    m_pWidget->setAttribute(Qt::WA_Hover, true);

    updateRubberBandStatus();
}

WidgetData::~WidgetData()
{
    m_pWidget->setMouseTracking(false);
    m_pWidget->setWindowFlags(m_windowFlags);
    m_pWidget->setAttribute(Qt::WA_Hover, false);

    delete m_pRubberBand;
    m_pRubberBand = nullptr;
}

QWidget* WidgetData::widget()
{
    return m_pWidget;
}

void WidgetData::handleWidgetEvent(QEvent *event)
{
    switch (event->type())
    {
    case QEvent::MouseButtonPress:      // 鼠标按下
        handleMousePressEvent(static_cast<QMouseEvent*>(event));
        break;
    case QEvent::MouseButtonRelease:    // 鼠标释放
        handleMouseReleaseEvent(static_cast<QMouseEvent*>(event));
        break;
    case QEvent::MouseMove:             // 鼠标移动
        handleMouseMoveEvent(static_cast<QMouseEvent*>(event));
        break;
    case QEvent::Leave:             // 鼠标离开
        handleLeaveEvent(static_cast<QMouseEvent*>(event));
        break;
    case QEvent::HoverMove:         // 鼠标悬停在部件内移动
        handleHoverMoveEvent(static_cast<QHoverEvent*>(event));
        break;
    default:
        break;
    }
}

void WidgetData::updateRubberBandStatus()
{
    if (d->m_bRubberBandOnMove || d->m_bRubberBandOnResize)
    {
        if (nullptr == m_pRubberBand)
            m_pRubberBand = new QRubberBand(QRubberBand::Rectangle);
    }
    else
    {
        delete m_pRubberBand;
        m_pRubberBand = nullptr;
    }
}

void WidgetData::updateCursorShape(const QPoint &gMousePos)
{
    if (m_pWidget->isFullScreen() || m_pWidget->isMaximized())
    {
        if (m_bCursorShapeChanged)
        {
            m_pWidget->unsetCursor();
        }
        return;
    }

    m_moveMousePos.recalculate(gMousePos, m_pWidget->frameGeometry());

    if(m_moveMousePos.m_bOnTopLeftEdge || m_moveMousePos.m_bOnBottomRightEdge)
    {
        m_pWidget->setCursor( Qt::SizeFDiagCursor );
        m_bCursorShapeChanged = true;
    }
    else if(m_moveMousePos.m_bOnTopRightEdge || m_moveMousePos.m_bOnBottomLeftEdge)
    {
        m_pWidget->setCursor( Qt::SizeBDiagCursor );
        m_bCursorShapeChanged = true;
    }
    else if(m_moveMousePos.m_bOnLeftEdge || m_moveMousePos.m_bOnRightEdge)
    {
        m_pWidget->setCursor( Qt::SizeHorCursor );
        m_bCursorShapeChanged = true;
    }
    else if(m_moveMousePos.m_bOnTopEdge || m_moveMousePos.m_bOnBottomEdge)
    {
        m_pWidget->setCursor( Qt::SizeVerCursor );
        m_bCursorShapeChanged = true;
    }
    else
    {
        if (m_bCursorShapeChanged)
        {
            m_pWidget->unsetCursor();
            m_bCursorShapeChanged = false;
        }
    }
}

void WidgetData::resizeWidget(const QPoint &gMousePos)
{
    QRect origRect;

    if (d->m_bRubberBandOnResize)
        origRect = m_pRubberBand->frameGeometry();
    else
        origRect = m_pWidget->frameGeometry();

    int left = origRect.left();
    int top = origRect.top();
    int right = origRect.right();
    int bottom = origRect.bottom();
    origRect.getCoords(&left, &top, &right, &bottom);

    int minWidth = m_pWidget->minimumWidth();
    int minHeight = m_pWidget->minimumHeight();

    if (m_pressedMousePos.m_bOnTopLeftEdge)
    {
        left = gMousePos.x();
        top = gMousePos.y();
    }
    else if (m_pressedMousePos.m_bOnBottomLeftEdge)
    {
        left = gMousePos.x();
        bottom = gMousePos.y();
    }
    else if (m_pressedMousePos.m_bOnTopRightEdge)
    {
        right = gMousePos.x();
        top = gMousePos.y();
    }
    else if (m_pressedMousePos.m_bOnBottomRightEdge)
    {
        right = gMousePos.x();
        bottom = gMousePos.y();
    }
    else if (m_pressedMousePos.m_bOnLeftEdge)
    {
        left = gMousePos.x();
    }
    else if (m_pressedMousePos.m_bOnRightEdge)
    {
        right = gMousePos.x();
    }
    else if (m_pressedMousePos.m_bOnTopEdge)
    {
        top = gMousePos.y();
    }
    else if (m_pressedMousePos.m_bOnBottomEdge)
    {
        bottom = gMousePos.y();
    }

    QRect newRect(QPoint(left, top), QPoint(right, bottom));

    if (newRect.isValid())
    {
        if (minWidth > newRect.width())
        {
            if (left != origRect.left())
                newRect.setLeft(origRect.left());
            else
                newRect.setRight(origRect.right());
        }
        if (minHeight > newRect.height())
        {
            if (top != origRect.top())
                newRect.setTop(origRect.top());
            else
                newRect.setBottom(origRect.bottom());
        }

        if (d->m_bRubberBandOnResize)
        {
            m_pRubberBand->setGeometry(newRect);
        }
        else
        {
            m_pWidget->setGeometry(newRect);
        }
    }
}

void WidgetData::moveWidget(const QPoint& gMousePos)
{
    if (d->m_bRubberBandOnMove)
    {
        m_pRubberBand->move(gMousePos - m_ptDragPos);
    }
    else
    {
        m_pWidget->move(gMousePos - m_ptDragPos);
    }
}

void WidgetData::handleMousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        m_bLeftButtonPressed = true;
        m_bLeftButtonTitlePressed = event->pos().y() < m_moveMousePos.m_nTitleHeight;

        QRect frameRect = m_pWidget->frameGeometry();
        m_pressedMousePos.recalculate(event->globalPos(), frameRect);

        m_ptDragPos = event->globalPos() - frameRect.topLeft();

        if (m_pressedMousePos.m_bOnEdges)
        {
            if (d->m_bRubberBandOnResize)
            {
                m_pRubberBand->setGeometry(frameRect);
                m_pRubberBand->show();
            }
        }
        else if (d->m_bRubberBandOnMove)
        {
            m_pRubberBand->setGeometry(frameRect);
            m_pRubberBand->show();
        }
    }
}

void WidgetData::handleMouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
    {
        m_bLeftButtonPressed = false;
        m_bLeftButtonTitlePressed = false;
        m_pressedMousePos.reset();
        if (m_pRubberBand && m_pRubberBand->isVisible())
        {
            m_pRubberBand->hide();
            m_pWidget->setGeometry(m_pRubberBand->geometry());
        }
    }
}

void WidgetData::handleMouseMoveEvent(QMouseEvent *event)
{
    if (m_bLeftButtonPressed)
    {
        if (d->m_bWidgetResizable && m_pressedMousePos.m_bOnEdges)
        {
            resizeWidget(event->globalPos());
        }
        else if (d->m_bWidgetMovable && m_bLeftButtonTitlePressed)
        {
            moveWidget(event->globalPos());
        }
    }
    else if (d->m_bWidgetResizable)
    {
        updateCursorShape(event->globalPos());
    }
}

void WidgetData::handleLeaveEvent(QEvent *event)
{
    Q_UNUSED(event)
    if (!m_bLeftButtonPressed)
    {
        m_pWidget->unsetCursor();
    }
}

void WidgetData::handleHoverMoveEvent(QHoverEvent *event)
{
    if (d->m_bWidgetResizable)
    {
        updateCursorShape(m_pWidget->mapToGlobal(event->pos()));
    }
}

FramelessHelper::FramelessHelper(QWidget *parent) :
    QWidget(parent),
    d(new FramelessHelperPrivate())
{
    //this->setObjectName("TitleWidget");

    d->m_bWidgetMovable = true;
    d->m_bWidgetResizable = true;
    d->m_bRubberBandOnResize = false;
    d->m_bRubberBandOnMove = false;
}

FramelessHelper::~FramelessHelper()
{
    QList<QWidget*> keys = d->m_widgetDataHash.keys();
    int size = keys.size();
    for (int i = 0; i < size; ++i)
    {
        delete d->m_widgetDataHash.take(keys[i]);
    }

    delete d;
}

///
/// \brief 事件过滤，进行移动，缩放等
/// \param obj
/// \param event
/// \return
///
bool FramelessHelper::eventFilter(QObject *obj, QEvent *event)
{
    switch (event->type())
    {
    case QEvent::MouseMove:     // 鼠标移动事件
    case QEvent::HoverMove:     // 鼠标在悬停部件内移动
    case QEvent::MouseButtonPress:      // 鼠标按下
    case QEvent::MouseButtonRelease:    // 鼠标释放
    case QEvent::Leave:         // 鼠标离开部件的边界
    {
        WidgetData *data = d->m_widgetDataHash.value(static_cast<QWidget*>(obj));
        if (data)
        {
            //qDebug() << "ok";
            data->handleWidgetEvent(event);
            return true;
        }
        break;
    }
    default:
        break;
    }
    return QObject::eventFilter(obj, event);
}

///
/// \brief 激活窗体
/// \param topLevelWidget
///
void FramelessHelper::activateOn(QWidget *topLevelWidget)
{
    if (!d->m_widgetDataHash.contains(topLevelWidget))
    {
        WidgetData *data = new WidgetData(d, topLevelWidget);
        d->m_widgetDataHash.insert(topLevelWidget, data);

        topLevelWidget->installEventFilter(this);
    }
}

///
/// \brief 移除窗体
/// \param topLevelWidget
///
void FramelessHelper::removeFrom(QWidget *topLevelWidget)
{
    WidgetData *data = d->m_widgetDataHash.take(topLevelWidget);
    if (data)
    {
        topLevelWidget->removeEventFilter(this);
        delete data;
    }
}

///
/// \brief 设置窗体移动
/// \param movable
///
void FramelessHelper::setWidgetMovable(bool movable)
{
    d->m_bWidgetMovable = movable;
}

///
/// \brief 设置窗体缩放
/// \param resizable
///
void FramelessHelper::setWidgetResizable(bool resizable)
{
    d->m_bWidgetResizable = resizable;
}

///
/// \brief 设置橡皮筋移动
/// \param movable
///
void FramelessHelper::setRubberBandOnMove(bool movable)
{
    d->m_bRubberBandOnMove = movable;
    QList<WidgetData*> list = d->m_widgetDataHash.values();
    foreach (WidgetData *data, list)
    {
        data->updateRubberBandStatus();
    }
}

///
/// \brief 设置橡皮筋缩放
/// \param resizable
///
void FramelessHelper::setRubberBandOnResize(bool resizable)
{
    d->m_bRubberBandOnResize = resizable;
    QList<WidgetData*> list = d->m_widgetDataHash.values();
    foreach (WidgetData *data, list)
    {
        data->updateRubberBandStatus();
    }
}

///
/// \brief 设置边框宽度
/// \param width
///
void FramelessHelper::setBorderWidth(uint width)
{
    if (width > 0)
    {
        CursorPosCalculator::m_nBorderWidth = static_cast<int>(width);
    }
}

///
/// \brief 设置标题栏高度
/// \param height
///
void FramelessHelper::setTitleHeight(uint height)
{
    if (height > 0)
    {
        CursorPosCalculator::m_nTitleHeight = static_cast<int>(height);
    }
}

///
/// \brief 返回窗体是否可移动
/// \return
///
bool FramelessHelper::widgetMovable()
{
    return d->m_bWidgetMovable;
}

///
/// \brief 返回窗体是否可缩放
/// \return
///
bool FramelessHelper::widgetResizable()
{
    return d->m_bWidgetResizable;
}

///
/// \brief 返回橡皮筋是否可移动
/// \return
///
bool FramelessHelper::rubberBandOnMove()
{
    return d->m_bRubberBandOnMove;
}

///
/// \brief 返回橡皮筋是否可缩放
/// \return
///
bool FramelessHelper::rubberBandOnResisze()
{
    return d->m_bRubberBandOnResize;
}

///
/// \brief 返回边界宽度
/// \return
///
uint FramelessHelper::borderWidth()
{
    return static_cast<uint>(CursorPosCalculator::m_nBorderWidth);
}

///
/// \brief 返回标题高度
/// \return
///
uint FramelessHelper::titleHeight()
{
    return static_cast<uint>(CursorPosCalculator::m_nTitleHeight);
}

WidgetPar::WidgetPar(QFrame *parent) :
    QFrame(parent)
{
    this->setObjectName("TitleWidget");

    m_pHelper = new FramelessHelper(this);
    m_pHelper->activateOn(this);  //激活当前窗体
    m_pHelper->setWidgetMovable(true);  //设置窗体可移动
    m_pHelper->setWidgetResizable(true);  //设置窗体可缩放
    m_pHelper->setRubberBandOnMove(false);  //设置橡皮筋效果-可移动
    m_pHelper->setRubberBandOnResize(false);  //设置橡皮筋效果-可缩放
}

void WidgetPar::setTitleHeight(unsigned int height)
{
    m_pHelper->setTitleHeight(height);  //设置窗体的标题栏高度
}

void WidgetPar::setWidgetResizable(bool state)
{
    m_pHelper->setWidgetResizable(state);  // 设置窗体是否可缩放
}

void WidgetPar::showEvent(QShowEvent *event)
{
    emit ShowSignal(event);
}

void WidgetPar::closeEvent(QCloseEvent *event)
{
    emit CloseSignal(event);
}
